package com.jumi.microservice.service.finance;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jumi.microservice.common.base.dto.ExportExcelCommonResponse;
import com.jumi.microservice.common.utils.EnumUtil;
import com.jumi.microservice.constant.compensation.AfterSaleStatusEnum;
import com.jumi.microservice.domain.SkuDTO;
import com.jumi.microservice.dto.finance.*;
import com.jumi.microservice.dto.finance.excel.GoodsDetailExcel;
import com.jumi.microservice.dto.reponse.FenXiaoReponse;
import com.jumi.microservice.dto.reponse.JmUserReponse;
import com.jumi.microservice.entity.OrderGoods;
import com.jumi.microservice.entity.UserOrder;
import com.jumi.microservice.enumerate.LogisticsStatusEnum;
import com.jumi.microservice.enumerate.OrderStatusEnum;
import com.jumi.microservice.enumerate.SelfFlagEnum;
import com.jumi.microservice.enums.FenXiaoType;
import com.jumi.microservice.enums.Level;
import com.jumi.microservice.mapper.OrderGoodsMapper;
import com.jumi.microservice.mapper.UserOrderMapper;
import com.jumi.microservice.material.dto.supplier.JmSupplierResponse;
import com.jumi.microservice.material.dto.warehouse.JmWarehouseResponse;
import com.jumi.microservice.material.service.IJmSupplierService;
import com.jumi.microservice.material.service.IJmWarehouseService;
import com.jumi.microservice.service.*;
import com.jumi.microservice.service.logistics.admin.SendService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * @author by mazhao
 * @Classname GoodsSaleDetailService
 * @Description TODO
 * @Date 2020/9/16 15:44
 */
@Service
public class GoodsSaleDetailService {

    private static final Logger log = LoggerFactory.getLogger(GoodsSaleDetailService.class);


    @Resource
    UserOrderMapper userOrderMapper;

    @DubboReference
    BasicDataService basicDataService;

    @Resource
    OrderGoodsMapper orderGoodsMapper;

    @DubboReference
    IJmSupplierService iJmSupplierService;

    @DubboReference
    IJmWarehouseService iWarehouseService;

    @DubboReference
    IFenXiaoService iFenXiaoService;

    @DubboReference
    IMemberService iUserService;

    @DubboReference
    ILevelConfigService iLevelConfigService;

    private static int batchSize = 500;

    /**
     * 商品销售明细列表 财务用
     *
     * @param request
     * @return
     */
    public GoodsSaleDetailResponse list(GoodsSaleDetailRequest request) {
        GoodsSaleDetailResponse goodsSaleDetailResponse = new GoodsSaleDetailResponse();
        QueryWrapper<OrderGoods> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("create_time");
        queryWrapper.and(q -> q.ge("goods_status", LogisticsStatusEnum.WAIT_SEND.getCode()).or()
                .eq("goods_status", LogisticsStatusEnum.CANCEL.getCode()).gt("after_seal_status", (byte) 0));
        if (request.getOrderCreateStartTime() != null) {
            queryWrapper.le("create_time", request.getOrderCreateEndTime())
                    .ge("create_time", request.getOrderCreateStartTime());
        }
        if (request.getSupplierId() != null) {
            queryWrapper.eq("supplier_id", request.getSupplierId());
        }
        if (request.getWarehouseId() != null) {
            queryWrapper.eq("real_warehouse", request.getWarehouseId());
        }
        if (request.getGoodsStatus() != null) {
            queryWrapper.eq("goods_status", request.getGoodsStatus());
        }
        if (request.getGoodsName() != null && !request.getGoodsName().trim().isEmpty()) {
            queryWrapper.like("goods_name", request.getGoodsName());
        }
        if (request.getAfterSaleStatus() != null) {
            queryWrapper.eq("after_seal_status", request.getAfterSaleStatus());
        }
        if (request.getOrderNo() != null && !request.getOrderNo().trim().isEmpty()) {
            queryWrapper.eq("order_no", request.getOrderNo());
        }
        Map<Long, SkuDTO> map;
        String goodsIds = null;
        List<GoodsDetail> result = new ArrayList<>();
        if (request.getMaterialsName() != null && !request.getMaterialsName().trim().isEmpty()) {
            //请求接口查询出所有的自营商城商品ID
            map = basicDataService.getMaterialInfoByIds4Order(new ArrayList<>(), request.getMaterialsName());
            if (map.isEmpty()) {
                goodsSaleDetailResponse.setTotal(0L);
                goodsSaleDetailResponse.setRows(result);
                goodsSaleDetailResponse.setSumOrderAmount(BigDecimal.ZERO);
                return goodsSaleDetailResponse;
            }
            Set<Long> spuIds = map.keySet();
            goodsIds = spuIds.stream().map(Object::toString).collect(Collectors.joining(","));
            queryWrapper.in("spu_id", spuIds);
        }
        IPage<OrderGoods> page = new Page<>(request.getPageNum(), request.getPageSize());
        IPage<OrderGoods> iPage = orderGoodsMapper.selectPage(page, queryWrapper);
        List<OrderGoods> goodsList = iPage.getRecords();
        if (goodsList.isEmpty()) {
            goodsSaleDetailResponse.setTotal(0L);
            goodsSaleDetailResponse.setRows(result);
            goodsSaleDetailResponse.setSumOrderAmount(BigDecimal.ZERO);
            return goodsSaleDetailResponse;
        }
        List<Long> goodsIdList = goodsList.stream().map(o -> o.getSpuId().longValue()).collect(Collectors.toList());
        map = basicDataService.getMaterialInfoByIds4Order(goodsIdList, "");
        Map<Integer, String> supplierMap = supplierMap();
        Map<Integer, String> warehouseMap = getWarehouseMap();
        for (OrderGoods g : goodsList) {
            GoodsDetail goodsDetail = new GoodsDetail();
            BeanUtils.copyProperties(g, goodsDetail);
            AfterSaleStatusEnum afterSaleStatusEnum = EnumUtil.getByCode(g.getAfterSealStatus().intValue(), AfterSaleStatusEnum.class);
            LogisticsStatusEnum logisticsStatusEnum = EnumUtil.getByCode(g.getGoodsStatus(), LogisticsStatusEnum.class);
            goodsDetail.setAfterSealStatus(afterSaleStatusEnum.getMsg());
            goodsDetail.setGoodsStatus(logisticsStatusEnum.getMsg());
            goodsDetail.setAfterSealAmount(g.getReturnCount());
            if (map != null && map.containsKey(g.getSpuId().longValue())) {
                goodsDetail.setMaterialsName(map.get(g.getSpuId().longValue()).getMaterialName());
                goodsDetail.setMaterialsAmount(map.get(g.getSpuId().longValue()).getMaterialCount()*g.getGoodsAmount());
            }
            goodsDetail.setGoodsCostPrice(g.getGoodsCostPrice().multiply(new BigDecimal(g.getGoodsAmount())));
            goodsDetail.setSupplierName("");
            if (g.getSelfFlag().equals(SelfFlagEnum.YES_SELF.getCode())) {
                if (warehouseMap.containsKey(g.getRealWarehouse())) {
                    goodsDetail.setSupplierName(warehouseMap.get(g.getRealWarehouse()));
                }
            } else {
                if (supplierMap.containsKey(g.getSupplierId())) {
                    goodsDetail.setSupplierName(supplierMap.get(g.getSupplierId()));
                }
            }
            goodsDetail.setRealPayPrice(g.getGoodsPrice().multiply(new BigDecimal(g.getGoodsAmount())).add(g.getGoodsFreightFee()));
            //请求接口获取推广费跟差价
            List<FenXiaoReponse> list = iFenXiaoService.getSumFenxiao(g.getOrderNo(), null, g.getGoodsId());
            goodsDetail.setGoodsSpreadPrice(BigDecimal.ZERO);
            goodsDetail.setGoodsServicePrice(BigDecimal.ZERO);
            for (FenXiaoReponse fenXiaoReponse : list) {
                if (fenXiaoReponse.getType().getValue().equals(FenXiaoType.推广收益.getValue())) {
                    goodsDetail.setGoodsSpreadPrice(fenXiaoReponse.getYongjin());
                } else if (fenXiaoReponse.getType().getValue().equals(FenXiaoType.服务收益.getValue())) {
                    goodsDetail.setGoodsServicePrice(fenXiaoReponse.getYongjin());
                }
            }
            result.add(goodsDetail);
        }
        goodsSaleDetailResponse.setRows(result);
        goodsSaleDetailResponse.setTotal(iPage.getTotal());
        if (request.getPageSize() != -1) {
            //统计订单总金额
            Map<String, BigDecimal> sumOrderAmountMap = orderGoodsMapper.sumOrderAmount(request.getGoodsName(),
                    request.getGoodsStatus(), request.getSupplierId(), request.getWarehouseId(),
                    request.getOrderCreateStartTime(), request.getOrderCreateEndTime(), request.getOrderNo(),
                    goodsIds, request.getAfterSaleStatus());
            goodsSaleDetailResponse.setSumOrderAmount(sumOrderAmountMap.get("amount"));
        }
        return goodsSaleDetailResponse;
    }


    /**
     * 获取接单费 差价用户列表
     *
     * @param request
     * @return
     */
    public List<UserInfo> getUserList(UserListRequest request) {
        List<UserInfo> result = new ArrayList<>();
        List<FenXiaoReponse> list = iFenXiaoService.getFenxiao(request.getOrderNo(), request.getGoodsId()).getData().getRecords();
        if (list.isEmpty()) {
            return result;
        }
        list = list.stream().filter(f -> f.getType().getValue().equals(request.getType())).collect(Collectors.toList());
        List<Integer> userIds = list.stream().map(FenXiaoReponse::getUid).collect(Collectors.toList());
        Map<Integer, JmUserReponse> userInfoMap = getJmUserMap(userIds);
        Map<Integer, Object> levelMap = memberLevel();
        for (FenXiaoReponse fenXiaoReponse : list) {
            UserInfo userInfo = new UserInfo();
            userInfo.setAmount(fenXiaoReponse.getYongjin());
            userInfo.setId(fenXiaoReponse.getUid());
            JmUserReponse jmUserReponse = null;
            if (userInfoMap.containsKey(fenXiaoReponse.getUid())) {
                jmUserReponse = userInfoMap.get(fenXiaoReponse.getUid());
            }
            userInfo.setTruename(jmUserReponse != null ? jmUserReponse.getTruename() : "");
            userInfo.setAvatar(jmUserReponse != null ? jmUserReponse.getAvatar() : "");
            userInfo.setLevel("");
            if (levelMap.containsKey(jmUserReponse.getLevel().getValue())) {
                userInfo.setLevel(levelMap.get(jmUserReponse.getLevel().getValue()).toString());
            }
            userInfo.setMobile(jmUserReponse != null ? jmUserReponse.getMobile() : "");
            userInfo.setName(jmUserReponse != null ? jmUserReponse.getName() : "");
            userInfo.setBelong(jmUserReponse.getIsJumi().getValue().equals(1) ? "聚米" : "非聚米");
            result.add(userInfo);
        }
        return result;
    }


    /**
     * 供应商对照
     *
     * @return
     */
    public Map<Integer, String> supplierMap() {
        List list = iJmSupplierService.list().getData();
        Map<Integer, String> map = new HashMap<>(list.size());
        for (Object object : list) {
            JmSupplierResponse jmSupplierResponse = JSON.parseObject(JSON.toJSONString(object), JmSupplierResponse.class);
            map.put(jmSupplierResponse.getSupplierId().intValue(), jmSupplierResponse.getSupplierCompanyName());
        }
        return map;
    }

    /**
     * 获取全部仓库信息
     *
     * @return
     */
    public Map<Integer, String> getWarehouseMap() {
        List<JmWarehouseResponse> list = iWarehouseService.findAll().getData();
        Map<Integer, String> map = new HashMap<>(list.size());
        for (JmWarehouseResponse jmWarehouseResponse : list) {
            map.put(jmWarehouseResponse.getWarehouseId().intValue(), jmWarehouseResponse.getWarehouseName());
        }
        return map;
    }

    /**
     * 导出
     *
     * @param request
     * @return
     */
    public ExportExcelCommonResponse<GoodsDetailExcel> excelExport(GoodsSaleDetailRequest request) {
        request.checkRequest();
        Map<Integer, String> supplierMap = supplierMap();
        Map<Integer, String> warehouseMap = getWarehouseMap();
        ExportExcelCommonResponse<GoodsDetailExcel> response = new ExportExcelCommonResponse<>();
        List<GoodsDetailExcel> result = new ArrayList<>();
        QueryWrapper<OrderGoods> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("create_time");
        queryWrapper.and(q -> q.ge("goods_status", LogisticsStatusEnum.WAIT_SEND.getCode()).or()
                .eq("goods_status", LogisticsStatusEnum.CANCEL.getCode()).gt("after_seal_status", (byte) 0));
        if (request.getOrderCreateStartTime() != null) {
            queryWrapper.le("create_time", request.getOrderCreateEndTime())
                    .ge("create_time", request.getOrderCreateStartTime());
        }
        if (request.getSupplierId() != null) {
            queryWrapper.eq("supplier_id", request.getSupplierId());
        }
        if (request.getWarehouseId() != null) {
            queryWrapper.eq("real_warehouse", request.getWarehouseId());
        }
        if (request.getGoodsStatus() != null) {
            queryWrapper.eq("goods_status", request.getGoodsStatus());
        }
        if (request.getGoodsName() != null && !request.getGoodsName().trim().isEmpty()) {
            queryWrapper.like("goods_name", request.getGoodsName());
        }
        if (request.getAfterSaleStatus() != null) {
            queryWrapper.eq("after_seal_status", request.getAfterSaleStatus());
        }
        if (request.getOrderNo() != null && !request.getOrderNo().trim().isEmpty()) {
            queryWrapper.eq("order_no", request.getOrderNo());
        }
        Map<Long, SkuDTO> map;
        if (request.getMaterialsName() != null && !request.getMaterialsName().trim().isEmpty()) {
            //请求接口查询出所有的自营商城商品ID
            map = basicDataService.getMaterialInfoByIds4Order(new ArrayList<>(), request.getMaterialsName());
            if (map.isEmpty()) {
                return response;
            }
            Set<Long> spuIds = map.keySet();
            queryWrapper.in("spu_id", spuIds);
        }
        IPage<OrderGoods> page = new Page<>(1, 1);
        IPage<OrderGoods> records = orderGoodsMapper.selectPage(page, queryWrapper);
        long total = records.getTotal();
        int c = (int) (total % batchSize == 0 ? total / batchSize : total / batchSize + 1);

        ExecutorService executor = Executors.newFixedThreadPool(c);
        Future<List<GoodsDetailExcel>> f_list;
        try {
            for (int i = 1; i <= c; i++) {
                IPage<OrderGoods> iPage = new Page<>(i, batchSize);
                f_list = executor.submit(new OrderNumThread(queryWrapper, iPage,supplierMap,warehouseMap));
                result.addAll(f_list.get());
            }
        } catch (InterruptedException e) {
            log.error("packTeam()方法线程<阻塞>异常!" + e);
        } catch (ExecutionException e) {
            log.error("packTeam()方法线程<崩溃>异常!" + e);
        } catch (Exception e) {
            log.error("packTeam()方法<其他>异常!" + e);
        } finally {
            executor.shutdown();
        }
        response.setData(result);
        response.setFileName("GoodsSaleDetail.xlsx");
        return response;
    }

    class OrderNumThread implements Callable<List<GoodsDetailExcel>> {

        private QueryWrapper queryWrapper;

        private IPage iPage;

        private Map<Integer, String> supplierMap;

        private  Map<Integer, String> warehouseMap;

        public OrderNumThread(QueryWrapper queryWrapper, IPage iPage, Map<Integer, String> supplierMap, Map<Integer, String> warehouseMap) {
            this.queryWrapper = queryWrapper;
            this.iPage = iPage;
            this.supplierMap = supplierMap;
            this.warehouseMap = warehouseMap;
        }

        @Override
        public List<GoodsDetailExcel> call() {
            List<GoodsDetailExcel> result = new ArrayList<>();
            List<OrderGoods> goodsList = orderGoodsMapper.selectPage(iPage, queryWrapper).getRecords();
            if (goodsList.isEmpty()) {
                return new ArrayList<>();
            }
            List<Long> goodsIdList = goodsList.stream().map(o -> o.getSpuId().longValue()).collect(Collectors.toList());
            Map<Long, SkuDTO> map = basicDataService.getMaterialInfoByIds4Order(goodsIdList, "");
            for (OrderGoods g : goodsList) {
                GoodsDetailExcel goodsDetail = new GoodsDetailExcel();
                BeanUtils.copyProperties(g, goodsDetail);
                AfterSaleStatusEnum afterSaleStatusEnum = EnumUtil.getByCode(g.getAfterSealStatus().intValue(), AfterSaleStatusEnum.class);
                LogisticsStatusEnum logisticsStatusEnum = EnumUtil.getByCode(g.getGoodsStatus(), LogisticsStatusEnum.class);
                goodsDetail.setAfterSealStatus(afterSaleStatusEnum.getMsg());
                goodsDetail.setGoodsStatus(logisticsStatusEnum.getMsg());
                goodsDetail.setAfterSealAmount(g.getReturnCount());
                if (map != null && map.containsKey(g.getSpuId().longValue())) {
                    goodsDetail.setMaterialsName(map.get(g.getSpuId().longValue()).getMaterialName());
                    goodsDetail.setMaterialsAmount(map.get(g.getSpuId().longValue()).getMaterialCount()*g.getGoodsAmount());
                }
                goodsDetail.setGoodsCostPrice(g.getGoodsCostPrice().multiply(new BigDecimal(g.getGoodsAmount())));
                goodsDetail.setSupplierName("");
                if (g.getSelfFlag().equals(SelfFlagEnum.YES_SELF.getCode())) {
                    if (warehouseMap.containsKey(g.getRealWarehouse())) {
                        goodsDetail.setSupplierName(warehouseMap.get(g.getRealWarehouse()));
                    }
                } else {
                    if (supplierMap.containsKey(g.getSupplierId())) {
                        goodsDetail.setSupplierName(supplierMap.get(g.getSupplierId()));
                    }
                }
                goodsDetail.setRealPayPrice(g.getGoodsPrice().multiply(new BigDecimal(g.getGoodsAmount())).add(g.getGoodsFreightFee()));
                //请求接口获取推广费跟差价
                List<FenXiaoReponse> list = iFenXiaoService.getSumFenxiao(g.getOrderNo(), null, g.getGoodsId());
                goodsDetail.setGoodsSpreadPrice(BigDecimal.ZERO);
                goodsDetail.setGoodsServicePrice(BigDecimal.ZERO);
                for (FenXiaoReponse fenXiaoReponse : list) {
                    if (fenXiaoReponse.getType().getValue().equals(FenXiaoType.推广收益.getValue())) {
                        goodsDetail.setGoodsSpreadPrice(fenXiaoReponse.getYongjin());
                    } else if (fenXiaoReponse.getType().getValue().equals(FenXiaoType.服务收益.getValue())) {
                        goodsDetail.setGoodsServicePrice(fenXiaoReponse.getYongjin());
                    }
                }
                result.add(goodsDetail);
            }
            return result;
        }
    }

    /**
     * 商品状态字典
     *
     * @return
     */
    public List<GoodsStatusResponse> goodsStatus() {
        LogisticsStatusEnum[] v = LogisticsStatusEnum.values();
        List<GoodsStatusResponse> list = new ArrayList<>(v.length);
        for (LogisticsStatusEnum logisticsStatusEnum : v) {
            if (logisticsStatusEnum.getCode() < (byte) 0) {
                continue;
            }
            GoodsStatusResponse goodsStatusResponse = new GoodsStatusResponse();
            goodsStatusResponse.setCode(logisticsStatusEnum.getCode());
            goodsStatusResponse.setMsg(logisticsStatusEnum.getMsg());
            list.add(goodsStatusResponse);
        }
        return list;
    }

    /**
     * 获取买家信息
     *
     * @param orderList
     * @return
     */
    public Map<Integer, JmUserReponse> getJmUserMap(List<Integer> orderList) {
        if (orderList.isEmpty()) {
            return new HashMap<>();
        }
        //获取买家信息
        List<JmUserReponse> jmUserResponseList = iUserService.getMemberByUids(orderList).getData();
        Map<Integer, JmUserReponse> map = new HashMap<>(jmUserResponseList.size());
        for (JmUserReponse jmUserReponse : jmUserResponseList) {
            map.put(jmUserReponse.getId(), jmUserReponse);
        }
        return map;
    }

    /**
     * 会员等级字典
     *
     * @return
     */
    public Map<Integer, Object> memberLevel() {
        List<Map<String, Object>> list = iLevelConfigService.getLevelConfig().getData();
        Map<Integer, Object> map = new HashMap<>(list.size());
        for (Map<String, Object> m : list) {
            map.put(Integer.parseInt(m.get("id").toString()), m.get("level_name"));
        }
        return map;
    }
}
